package org.ioriframework.plugin.maven.packaging.handlers;

import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.ioriframework.plugin.maven.BaseHandler;
import org.ioriframework.plugin.maven.Constants;
import org.ioriframework.plugin.maven.Executorhandler;
import org.ioriframework.plugin.maven.console.ConsoleFactory;
import org.ioriframework.plugin.maven.console.ConsoleService;
import org.ioriframework.plugin.maven.util.MavenUtils;
import org.ioriframework.plugin.maven.util.PreferenceUtils;
import org.ioriframework.plugin.maven.util.StringUtils;

/**
 * 打包任务处理类
 * 执行任务时，从Process返回流中读取日志，并输出到控制台
 * @author iori
 *
 */
public class CommandHandler extends BaseHandler {

	/**
	 * 打包环境
	 */
	private String env;
	
	/**
	 * EAR包输出目录
	 */
	private String earTarget;
	
	/**
	 * EAR包名称
	 */
	private String earFileName;
	
	/**
	 * 开始打包
	 */
	@Override
	public void run() {
		// 启动打包任务
		FutureTask<Integer> task = new FutureTask<Integer>(new Callable<Integer>() {
			public Integer call() {
				try {
					// 执行打包命令
					process(buildCommand(StringUtils.format(Constants.COMMAND_PACKAGE, PreferenceUtils.getBoolean(Constants.P_SKIP_TEST), getEnv())));
				} catch (Exception e) {
					ConsoleService.printlnError2Console("Process run error, " + e.getMessage());
				} finally {
					// 清除当前console实例
					ConsoleFactory.removeCurrentConsole();
				}
				return 0;
			}
		});
		// 启动新线程执行任务
		Executorhandler.getInstance().execute(task);
	}
	
	@Override
	public void processSuccessCallback() {
		if (!StringUtils.isNullOrEmpty(getEarTarget()) 
				&& !StringUtils.isNullOrEmpty(getEarFileName())) {
			Path earPath = getEarPath();
			if (earPath != null) {
				// 存在则覆盖
				try {
					Files.move(earPath, Paths.get(getEarTarget() + getEarFileName()), StandardCopyOption.REPLACE_EXISTING);
				} catch (IOException e) {
					ConsoleService.printlnError2Console("[ERROR] Move ear to " + getEarTarget() + getEarFileName() + " failed.");
				}
				ConsoleService.println2Console("Move ear to " + getEarTarget() + getEarFileName() + " end.");
			}
		}
	}

	/**
	 * 获取parent项目中pom.xml的路径
	 */
	@Override
	protected String getPomPath() {
		// 如果当前任务中pom路径已经存在，直接返回路径
		if (!StringUtils.isNullOrEmpty(ConsoleFactory.currentConsole().getPomPath())) {
			return ConsoleFactory.currentConsole().getPomPath();
		}
		Map<String, String> projectInfo = MavenUtils.findProjectInfo("pom");
		// 如果没有项目，执行异常
		if (projectInfo == null || projectInfo.isEmpty()) {
			throw new RuntimeException("[ERROR]工作空间中没有项目");
		}
		// pom.xml全路径
		String parentPomPath = projectInfo.get("parentPomPath");
		// 项目名称
		String parentProjectName = projectInfo.get("parentProjectName");
		ConsoleService.println2Console("Load pom.xml path: " + parentPomPath);
		// 如果无法找到parent项目的pom.xml，抛出异常
		if (StringUtils.isNullOrEmpty(parentPomPath)) {
			throw new RuntimeException("[ERROR] 无法找到parent项目的pom.xml文件，请检查项目配置.");
		}
		// 设置当前任务对应的pom.xml文件路径
		ConsoleFactory.currentConsole().setPomPath(parentPomPath);
		// 设置当前任务对应的项目名称
		ConsoleFactory.currentConsole().setProjectName(parentProjectName);
		return parentPomPath;
	}
	
	/**
	 * 获取maven打包后EAR的Path
	 * @return
	 */
	public Path getEarPath() {
		// 获取工作空间中的所有项目
		IWorkspace workspace = ResourcesPlugin.getWorkspace();
		IWorkspaceRoot root = workspace.getRoot();
		IProject[] projects = root.getProjects();
		// 如果没有项目，执行异常
		if (projects == null || projects.length < 1) {
			return null;
		}
		// EAR路径
		Path earPath = null;
		// 找工作空间中packagingType为ear的项目
		for (IProject project : projects) {
			// 只取打开的项目
			if (project.isOpen()) {
				String pomPath = project.getLocation() + "/pom.xml";
				try {
					String packagingType = MavenUtils.findPackaging(pomPath);
					if ("ear".equals(packagingType)) {
						// 遍历target文件夹下面的所有文件
						DirectoryStream<Path> paths = Files.newDirectoryStream(Paths.get(project.getLocation() + "/target"));
						try {
							for (Path p : paths) {
								if (!Files.isDirectory(p) && p.toString().endsWith(".ear")) {
									earPath = p;
									ConsoleService.println2Console("Load ear path: " + earPath);
									break;
								}
							}
						} finally {
							if (paths != null) {
								paths.close();
							}
						}
						// XXX 目前只取工作空间中的一个ear项目
						break;
					}
				} catch (Exception e) {
					ConsoleService.printlnWarning2Console("[WARNING]获取packagingType失败，此项目不是maven项目. " + e.getMessage());
				}
			}
		}
		return earPath;
	}
	
	public String getEnv() {
		return StringUtils.isNullOrEmpty(env) ? Constants.DEFAULT_ENV : env;
	}
	
	public void setEnv(String env) {
		this.env = env;
	}
	
	public String getEarTarget() {
		// earTarget以"/"结尾
		if (!StringUtils.isNullOrEmpty(earTarget) && !earTarget.replace("\\", "/").endsWith("/")) {
			earTarget += "/";
		}
		return earTarget;
	}
	
	public void setEarTarget(String earTarget) {
		this.earTarget = earTarget;
	}
	
	public String getEarFileName() {
		// earFileName以".ear"结尾
		if (!StringUtils.isNullOrEmpty(earFileName) && !earFileName.endsWith(".ear")) {
			earFileName += ".ear";
		}
		return earFileName;
	}
	
	public void setEarFileName(String earFileName) {
		this.earFileName = earFileName;
	}

}
